#include <cstdio>
#include <cstring>
#include <functional>
#include <iostream>

using namespace std;
class MyString {
  public:
    static size_t DCtor;
    static size_t Ctor;
    static size_t CCtor;
    static size_t CAsgn;
    static size_t MCtor;
    static size_t MAsgn;
    static size_t Dtor;

  private:
    char* data;
    size_t len;
    void init_data(const char* s) {
        data = new char[len + 1];
        memcpy(data, s, len);
        data[len] = '\0';
    }

  public:
    MyString() : data(0), len(0) { ++DCtor; }
    MyString(const char* p) : len(strlen(p)) {
        ++Ctor;
        init_data(p);
    }
    MyString(const MyString& obj) : len(obj.len) {
        ++CCtor;
        init_data(obj.data);
    }
    MyString(MyString&& obj) noexcept : data(obj.data), len(obj.len) {
        ++MCtor;
        obj.len = 0;
        obj.data = 0;
    }
    MyString& operator=(const MyString& obj) {
        ++CAsgn;
        if (this != &obj) {
            if (data)
                delete data;
            len = obj.len;
            init_data(obj.data);
        }
        return *this;
    }

    MyString& operator=(MyString&& obj) noexcept {
        ++MAsgn;
        if (this != &obj) {
            if (data)
                delete data;
            len = obj.len;
            data = obj.data;
            obj.len = 0;
            obj.data = 0;
        }
        return *this;
    }

    ~MyString() {
        ++Dtor;
        if (data)
            delete data;
        data = 0;
        len = 0;
    }

    bool operator<(const MyString& obj) const {
        return std::string(this->data) < std::string(obj.data);
    }

    bool operator==(const MyString& obj) const {
        return std::string(this->data) == std::string(obj.data);
    }

    char* get() const { return data; }
};

size_t MyString::Ctor = 0;
size_t MyString::DCtor = 0;
size_t MyString::CCtor = 0;
size_t MyString::CAsgn = 0;
size_t MyString::MCtor = 0;
size_t MyString::MAsgn = 0;
size_t MyString::Dtor = 0;
#define Prints(x) { cout << #x << "=\t" << T::x << endl; }

template <typename T> void printMyStringStaticData(const T& x) {
    cout << "typeid.name=" << typeid(x).name() << endl;
    Prints(CCtor);
    Prints(MCtor);
    Prints(CAsgn);
    Prints(MAsgn);
    Prints(Dtor);
    Prints(Ctor);
    Prints(DCtor);
}
namespace std {

template <> struct hash<MyString> : public __hash_base<size_t, MyString> {
    size_t operator()(const MyString& obj) const noexcept {
        return std::hash<std::string>()(std::string(obj.get()));
    }
};

} // namespace std

#include <ctime>
#include <iterator>
#include <cstdlib>
#include <vector>
#include <list>
#include <deque>
#include <set>
#include <unordered_set>

template<typename T>
void testMoveable0(T c1,long value) {

    srand(time(0));
    char buf[10];
    typedef typename iterator_traits<typename T::iterator>::value_type vtype;
    clock_t timeStart = clock();
    for(long i = 0; i != value; ++i)
    {
        snprintf(buf,10,"%d",rand() );
        auto ite = c1.end();
        c1.insert(ite,vtype(buf));
    }
    cout<<"construct time:"<<clock()-timeStart<<endl;
    cout<<"size()="<<c1.size()<<endl;
    printMyStringStaticData(*(c1.begin()));

    T c11(c1);
    T c12(std::move(c1));
    c11.swap(c12);
    return ;
}
void testMoveable()
{
    testMoveable0(std::vector<MyString>(),50000);

}